﻿using System;

namespace JESAI.DistributedLock.ZooKeeper;

/// <summary>
/// 实现了 <see cref="IDistributedLockProvider"/> 用于 <see cref="ZooKeeperDistributedLock"/>,
/// <see cref="IDistributedReaderWriterLockProvider"/> 用于 <see cref="ZooKeeperDistributedReaderWriterLock"/>,
/// 和 <see cref="IDistributedSemaphoreProvider"/> 用于 <see cref="ZooKeeperDistributedSemaphore"/>.
/// </summary>
public sealed class ZooKeeperDistributedSynchronizationProvider : IDistributedLockProvider, IDistributedReaderWriterLockProvider, IDistributedSemaphoreProvider
{
    private readonly ZooKeeperPath _directoryPath;
    private readonly string _connectionString;
    private readonly Action<ZooKeeperDistributedSynchronizationOptionsBuilder>? _options;

    /// <summary>
    /// 构造一个提供者，使用指定的 <paramref name="connectionString"/> 和 <paramref name="options"/>。锁和信号量节点将在根目录 '/' 中创建。
    /// </summary>
    public ZooKeeperDistributedSynchronizationProvider(string connectionString, Action<ZooKeeperDistributedSynchronizationOptionsBuilder>? options = null)
        : this(ZooKeeperPath.Root, connectionString, options) { }

    /// <summary>
    /// 构造一个提供者，使用指定的 <paramref name="connectionString"/> 和 <paramref name="options"/>。锁和信号量节点将在指定的 <paramref name="directoryPath"/> 中创建。
    /// </summary>
    public ZooKeeperDistributedSynchronizationProvider(ZooKeeperPath directoryPath, string connectionString, Action<ZooKeeperDistributedSynchronizationOptionsBuilder>? options = null)
    {
        this._directoryPath = directoryPath != default ? directoryPath : throw new ArgumentNullException(nameof(directoryPath));
        this._connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
        this._options = options;
    }

    /// <summary>
    /// 使用给定的 <paramref name="name"/> 创建一个 <see cref="ZooKeeperDistributedLock"/>.
    /// </summary>
    public ZooKeeperDistributedLock CreateLock(string name) =>
        new(this._directoryPath, name, this._connectionString, this._options);

    IDistributedLock IDistributedLockProvider.CreateLock(string name) => this.CreateLock(name);

    /// <summary>
    /// 使用给定的 <paramref name="name"/> 创建一个 <see cref="ZooKeeperDistributedReaderWriterLock"/>.
    /// </summary>
    public ZooKeeperDistributedReaderWriterLock CreateReaderWriterLock(string name) =>
        new(this._directoryPath, name, this._connectionString, this._options);

    IDistributedReaderWriterLock IDistributedReaderWriterLockProvider.CreateReaderWriterLock(string name) => this.CreateReaderWriterLock(name);

    /// <summary>
    /// 使用给定的 <paramref name="name"/> 和 <paramref name="maxCount"/> 创建一个 <see cref="ZooKeeperDistributedSemaphore"/>.
    /// </summary>
    public ZooKeeperDistributedSemaphore CreateSemaphore(string name, int maxCount) =>
        new(this._directoryPath, name, maxCount, this._connectionString, this._options);

    IDistributedSemaphore IDistributedSemaphoreProvider.CreateSemaphore(string name, int maxCount) => this.CreateSemaphore(name, maxCount);
}
